import java.util.Iterator;
import java.util.Vector;

public class Pattern 
{
	private Vector<Segment> allSegments;
	private Pixel[][] originalImage;
	private Pixel[][] markedImage;
	private boolean[][] binaryImage;
	private IKEA ikea;
	int width;
	int height;
	
	/*First element of array is -100 because moments are 1,2,...
	 *There is no moment 0*/
	private static final double[] Imoments = {-100,0.19321989586855212,0.009260029327100615,
		3.765628470540864E-6,4.831670585260763E-8,2.0550774537262777E-14,4.647965099285174E-9,
		0.007018474708088379,-4.646639705860319E-7,-4.566103132182228E-8,-2.0417367664684746E-13};
	
	private static final double[] Kmoments = {-100,0.20168644972474384,
		0.0033347054327603053,1.2983700876109775E-4,2.8396952754270034E-5,
		1.0196497093671965E-9,1.4732107849947998E-6,
		0.009335679642452828,-1.2680007000853463E-5,-2.0656741352045896E-6,6.093009627362122E-11};
	
	private static final double[] Emoments = {-100,0.18900517081039933,9.098708398083977E-5,
		3.4996755827959155E-5,4.5159472832322204E-5,-1.4870694986522219E-9
		-3.544144862358973E-7,0.00890799187727185,1.2703396255453804E-6,-1.073342727643959E-6,
		4.4321062645381934E-11};
	
	private static final double[] Amoments = {-100,0.19698459167000779,0.0021287160722760923,
		0.0019537424429191897, 1.1184778365784452E-4,-5.1433636563416054E-8,-4.722764067033848E-6,
		0.009168553320780905,-2.3023683240766814E-4,-1.93063632065629E-5,-3.1977988391091926E-8};
	
	private static final SegMomentsList[] IKEAPATTERNS = {
		new SegMomentsList(0.17234621664930327,0.4629627101503544,0.3103448275862069,Imoments),
		new SegMomentsList(0.5781560720715555,0.09364650163517363,0.24675324675324675,Kmoments),
		new SegMomentsList(0.7015891288174192,0.188468213358963,0.18206521739130435,Emoments),
		new SegMomentsList(0.459422567766655,0.0,0.2857142857142857,Amoments)
	};
	
	public Pattern(Vector<Segment> segments, Pixel[][] oImage,boolean[][] b, int w, int h)
	{
		allSegments = segments;
		width = w;
		height = h;
		originalImage = oImage;
		binaryImage = b;
		markedImage = new Pixel[width][height];
		markedImage = oImage;
		ikea = new IKEA();
	}
	
	public void doRecognizing()
	{
		Log.d("Pattern", "Starting recognition!");
		
		for (Iterator<Segment> iter = allSegments.iterator(); iter.hasNext();) 
		{
            Segment segment = iter.next();
            compareSingleSegmentWithPattern(segment);
        }
		
		checkIfIKEA();
		drawFrame();
		Log.d("Pattern", "Ending recognition!");
	}
	
	private void compareSingleSegmentWithPattern(Segment segment)
	{
		SegMomentsList ml = segment.getMoments();
		
		/*compare all letters with this segment*/
		
		/*comparing I*/
		if(ml.W3>=0.07 && ml.W3<=0.19)
		{System.out.println("I1");
			if(ml.W7_Lp1>=0.43 && ml.W7_Lp1<=0.58)
			{System.out.println("I2");
				if(ml.M[2]>=0.001 && ml.M[2]<=0.01)
				{System.out.println("I3");
					if(ml.M[7]>=0.0065 && ml.M[7]<=0.072)
					{System.out.println("I4");
						if(ml.W8_Lp2>=0.27 && ml.W8_Lp2<=0.33)
						{System.out.println("I5");
							if(ml.M[10]>=-2.00E-12 && ml.M[0]<=2.00E-17)
							{
								Log.d("Pattern", "I FOUND LETTER I !!!");
	                            segment.setLetter(LetterType.LETTER_I);
	                            markSegment(segment, 255,0,0);
	                            return;
							}
						}
					}
				}
			}
		}
		
		/*comparing K*/
		if(ml.W3>=0.47 && ml.W3<=0.6)
		{System.out.println("K1");
			if(ml.W7_Lp1>=0.06 && ml.W7_Lp1<=0.2)
			{System.out.println("K2");
				if(ml.W8_Lp2>=0.2 && ml.W8_Lp2<=0.31)
				{System.out.println("K3");
					if(ml.M[10]>=5.0E-11 && ml.M[10]<=2.0E-10)
					{System.out.println("K4");
						if(ml.M[6]>=7.9E-7 && ml.M[6]<=7.94E-6)
						{System.out.println("K5");
							if(ml.M[5]>=1.0E-11 && ml.M[5]<=1.0E-8)
							{
								Log.d("Pattern", "I FOUND LETTER K !!!");
	                            segment.setLetter(LetterType.LETTER_K);
	                            markSegment(segment, 255,0,255);
	                            return;
							}
						}
					}
				}
			}
		}
		
		/*comparing E*/
		if(ml.W3>=0.62 && ml.W3<=0.794)
		{System.out.println("E1");			
			if(ml.W7_Lp1>=0.110 && ml.W7_Lp1<=0.21)
			{System.out.println("E2");
				if(ml.W8_Lp2>=0.130 && ml.W8_Lp2<=0.217)
				{System.out.println("E3");
					if(ml.M[2]>=1.0E-5 && ml.M[2]<=5.0E-3)
					{System.out.println("E4");
						if(ml.M[4]>=2.0E-5 && ml.M[4]<=8.14E-5)
						{System.out.println("E5");
							if(ml.M[8]>=1.0E-7 && ml.M[8]<=1.0E-5)
							{
								Log.d("Pattern", "I FOUND LETTER E !!!");
	                            segment.setLetter(LetterType.LETTER_E);
	                            markSegment(segment,0,255,255);
	                            return;
							}
						}
					}
				}
			}
		}
		
		/*comparing A*/	
		if(ml.W3>=0.30 && ml.W3<=0.47)
		{System.out.println("A1");
			if(ml.W7_Lp1>=0.0 && ml.W7_Lp1<=0.05)
			{System.out.println("A2");
				if(ml.M[3]>=0.001 && ml.M[3]<=0.003)
				{System.out.println("A3");
					if(ml.M[4]>=8.0E-5 && ml.M[4]<=3.0E-4)
					{System.out.println("A4");
						if(ml.M[5]>=-1.0E-7 && ml.M[5]<=-1.0E-8)
						{System.out.println("A5");
							if(ml.M[8]>=-3.02E-4 && ml.M[8]<=1.0E-4)
							{
								Log.d("Pattern", "I FOUND LETTER A !!!");
	                            segment.setLetter(LetterType.LETTER_A);
	                            markSegment(segment,0,255,0);
	                            return;
							}
						}
					}
				}
			}
		}
		
	}
	
	private void markSegment(Segment s, int r, int g, int b) 
	{        
        int[][] colors = {{255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0}, {0, 255, 255}, {128, 128, 128}};
        Vector<SegmentPiece> spList = s.getPixels();
        for (Iterator<SegmentPiece> iterator = spList.iterator(); iterator.hasNext();) 
        {
        	SegmentPiece sp = iterator.next();
            markedImage[sp.x][sp.y] = new Pixel(r,g,b);
        }
    }

	private void checkIfIKEA()
	{
		IKEA ikeaText = new IKEA();
		for (Iterator<Segment> iterator = allSegments.iterator(); iterator.hasNext();) 
		{
            Segment segment = iterator.next();
            
            if (segment.getLetter() == LetterType.LETTER_E) 
            {
                Log.d("Pattern", "I have E letter! Continue..");
                int weights[] = segment.getWeights();
                
                int sizeSeg = segment.getRectArea();
                int maxDiameter = segment.getMaxDiameter();
                
                ikeaText.addLetter(segment);

                /* now looking for A letter*/
                for (Iterator<Segment> iterator2 = allSegments.iterator(); iterator2.hasNext();) 
                {
                    Segment segment2 = iterator2.next();
                    if (segment.getId() != segment2.getId()) 
                    {
                        if (segment2.getLetter() == LetterType.LETTER_A) 
                        {
                        	Log.d("Pattern", "I have A letter! Continue..");
                        	int weights2[] = segment2.getWeights();
                            
                            double dist2 = Math.sqrt(Math.pow(weights[0] - weights2[0], 2) + Math.pow(weights[1] - weights2[1], 2));
                            if (dist2 < 2 * maxDiameter) 
                            {
                                Log.d("Pattern", "I have E and A letters! Continue..");                               
                                ikeaText.addLetter(segment2);                                
                                break;
                            }
                        }
                    }
                }
                
                /* now looking for K letter*/
                for (Iterator<Segment> iterator2 = allSegments.iterator(); iterator2.hasNext();) 
                {
                    Segment segment2 = iterator2.next();
                    if (segment.getId() != segment2.getId()) {
                        if (segment2.getLetter() == LetterType.LETTER_K) 
                        {
                        	Log.d("Pattern", "I have K letter! Continue..");
                        	int weights2[] = segment2.getWeights();
                            
                        	double dist2 = Math.sqrt(Math.pow(weights[0] - weights2[0], 2) + Math.pow(weights[1] - weights2[1], 2));
                            int sizeSeg2 = segment2.getRectArea();
                            
                            if (dist2 < 2 * maxDiameter && (Math.abs(sizeSeg - sizeSeg2) < sizeSeg * 0.5)) 
                            {
                            	Log.d("Pattern", "I have E and K letters! Continue..");
                               
                                ikeaText.addLetter(segment2);
                                
                                /* now looking for I letter*/
                                for (Iterator<Segment> ii = allSegments.iterator(); ii.hasNext();) 
                                {
                                    Segment segment3 = ii.next();
                                    
                                    if (segment3.getLetter() == LetterType.LETTER_I) 
                                    {
                                    	Log.d("Pattern", "I have I letter! Continue..");
                                    	int weights3[] = segment3.getWeights();
                                        
                                    	double dist3 = Math.sqrt(Math.pow(weights2[0] - weights3[0], 2) + Math.pow(weights2[1] - weights3[1], 2));
                                        int sizeSeg3 = segment3.getRectArea();
                                        
                                        if (dist3 < 2 * maxDiameter && (Math.abs(sizeSeg2 - sizeSeg3) < sizeSeg2 * 0.75)) 
                                        {
                                        	Log.d("Pattern", "I have K and I letters! Continue..");                                            
                                            ikeaText.addLetter(segment3);                                           
                                        }
                                    }
                                }                                
                                break;
                            }
                        }
                    }
                }                                
            }
		}
		
		ikea = ikeaText;
		Log.d("Pattern","Ending looking for IKEA text");
	}
	
	private void drawFrame()
	{		
        Vector<Segment> symbolSegments = ikea.getLetters();
        int top = 10000;
        int bottom = -1;
        int left = 10000;
        int right = -1;
        
        for (Iterator<Segment> iterator2 = symbolSegments.iterator(); iterator2.hasNext();) 
        {
            Segment segment = iterator2.next();
            if (segment.getLetter() == LetterType.LETTER_A) 
            {
                int[] t = segment.getBorders();
                
                if (t[0] < left) 
                    left = t[0];                
                if (t[1] > right) 
                    right = t[1];                
                if (t[2] < top) 
                    top = t[2];                
                if (t[3] > bottom) 
                    bottom = t[3];                
            }
            if (segment.getLetter() == LetterType.LETTER_E) {
                int[] t = segment.getBorders();
                
                if (t[0] < left) 
                    left = t[0];                
                if (t[1] > right) 
                    right = t[1];                
                if (t[2] < top) 
                    top = t[2];                
                if (t[3] > bottom) 
                    bottom = t[3];                
            }
            if (segment.getLetter() == LetterType.LETTER_K) 
            {
                int[] t = segment.getBorders();
                
                if (t[0] < left) 
                    left = t[0];                
                if (t[1] > right) 
                    right = t[1];                
                if (t[2] < top) 
                    top = t[2];
                if (t[3] > bottom) 
                    bottom = t[3];                
            }
            if (segment.getLetter() == LetterType.LETTER_I) 
            {
                int[] t = segment.getBorders();
               
                if (t[0] < left) 
                    left = t[0];                
                if (t[1] > right) 
                    right = t[1];                
                if (t[2] < top) 
                    top = t[2];                
                if (t[3] > bottom)
                    bottom = t[3];                
            }
        }
                
        int r = 255;
        int g = 255;
        int b = 0;
                
        for (int x = 0; x < right - left; ++x) 
        {
        	originalImage[left + x][top] = new Pixel(r, g, b);
        	originalImage[left + x][bottom] = new Pixel(r, g, b);
        }
        
        for (int y = 0; y < bottom - top; ++y) 
        {
        	originalImage[left][top + y] = new Pixel(r, g, b);
        	originalImage[right][top + y] = new Pixel(r, g, b);
        }        
    }

	public Pixel[][] getOriginalImage()
	{
		return originalImage;
	}
	
	public Pixel[][] getMarkedImage() 
	{
		return markedImage;
	}
}
